package com.github.llyb120.szuniver.config;

import com.mongodb.*;
import com.mongodb.client.MongoDatabase;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import static com.github.llyb120.json.Json.*;

@Configuration
public class MongoConfiguration {
    public static MongoDatabase db;
    public static MongoDatabase commonDb;
    public static MongoDatabase authDb;
    //    public static MongoDatabase v20db;
    public static MongoClient mongoClient;
    private static String CoreDatabase;// = "hz-bpm-organ";
    private static String ClusterPrefix;
    //    private static String CommonDatabase = "bpm-common";
//    private static String V20Database = "hz-v20";
    private static Map<String, MongoDatabase> dbs = new HashMap<>();
    private static ReentrantLock mutex = new ReentrantLock();


    @Bean
    public MongoDatabase mongoDatabase(){
        start();
        return db;
    }
//    static {
//       start();
//    }

//    public static MongoDatabase getDB(String dbName){
//        mutex.lock();
//        if (dbName.equals("core")) {
//            dbName = CoreDatabase;//"hz-bpm-organ";
//        } else {
//            dbName = ClusterPrefix + dbName;
//        }
//        try{
//            MongoDatabase _db = dbs.get(dbName);
//            if (_db == null) {
//                _db = mongoClient.getDatabase(dbName);
//                dbs.put(dbName, _db);
//            }
//            return _db;
//        } finally {
//            mutex.unlock();
//        }
//    }

    @Value("${spring.data.mongodb.host}")
    String MONGO_HOST;
    @Value("${spring.data.mongodb.username}")
    String MONGO_USERNAME;
    @Value("${spring.data.mongodb.password}")
    String MONGO_PASSWORD;
    @Value("${spring.data.mongodb.database}")
    String MONGO_DATABASE;
    @Value("${spring.data.mongodb.authentication-database}")
    String AUTH_DB_NAME;

    private void start() {
        String cfg = MONGO_HOST;//config.var.s("mongo");
        int colon = cfg.indexOf(":");
        String host = "127.0.0.1";
        int port = 27027;
        if (colon > -1) {
            host = cfg.substring(0, colon);
            port = Integer.parseInt(cfg.substring(colon + 1));
        }
        //   连接到 mongodb 服务
        MongoCredential credential = null;
        String mongoUsername = MONGO_USERNAME;//config.var.ss("mongo-username");
        String mongoPassword = MONGO_PASSWORD;//config.var.ss("mongo-password");
        if (!mongoUsername.isEmpty()) {
            credential = MongoCredential.createCredential(mongoUsername, AUTH_DB_NAME, mongoPassword.toCharArray());
        }
        mongoClient = new MongoClient(new ServerAddress(host, port), (List) a(credential == null ? undefined : credential));
//        //连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址
//        //ServerAddress()两个参数分别为 服务器地址 和 端口
//        ServerAddress serverAddress = new ServerAddress("47.94.97.138",27017);
//        List<ServerAddress> addrs = new ArrayList<ServerAddress>();
//        addrs.add(serverAddress);
//        //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
//        MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
//        List<MongoCredential> credentials = new ArrayList<MongoCredential>();
//        credentials.add(credential);
//        //通过连接认证获取MongoDB连接
//        MongoClient mongoClient = new MongoClient(addrs);
//        //连接到数据库
//        MongoDatabase mongoDatabase = mongoClient.getDatabase("databaseName");

        // 大部分用户使用mongodb都在安全内网下，但如果将mongodb设为安全验证模式，就需要在客户端提供用户名和密码：
        // boolean auth = db.authenticate(myUserName, myPassword);
        MongoClientOptions.Builder options = new MongoClientOptions.Builder();
//        options.retr
//         options.autoConnectRetry(true);// 自动重连true
//         options.maxAutoConnectRetryTime(10); // the maximum auto connect retry time
        options.connectionsPerHost(300);// 连接池设置为300个连接,默认为100
        options.connectTimeout(15000);// 连接超时，推荐>3000毫秒
        options.maxWaitTime(5000); //
        options.socketTimeout(0);// 套接字超时时间，0无限制
        options.threadsAllowedToBlockForConnectionMultiplier(5000);// 线程队列数，如果连接线程排满了队列就会抛出“Out of semaphores to get db”错误。
        options.writeConcern(WriteConcern.SAFE);//
        options.build();

        //   连接到数据库
//        try{
//            MongoDatabase proxyDb = (MongoDatabase) Proxy.newProxyInstance(MongoDatabase.class.getClassLoader(), new Class[]{MongoDatabase.class}, new ProxyHandler());
//            db = proxyDb;
//            commonDb = getDB("core");
            commonDb = db = authDb = mongoClient.getDatabase(MONGO_DATABASE);
//            String authDbName = AUTH_DB_NAME;//config.var.ss("auth-db-name");
//            if(!authDbName.isEmpty()){
//                authDb = mongoClient.getDatabase(authDbName);
//            }
//            commonDb = mongoClient.getDatabase(CommonDatabase);
//        } catch (Exception e){
//            e.printStackTrace();
//        }
//        v20db = mongoClient.getDatabase(V20Database);
    }

    /**
     * 关闭Mongodb
     */
    public void close() {
        if (mongoClient != null) {
            mongoClient.close();
            mongoClient = null;
        }
    }
}
